import deepMerge from "../function/deepMerge";
import validate from "../function/test";
class Request {
    // 设置全局默认配置
    setConfig(customConfig) {
        // 深度合并对象，否则会造成对象深层属性丢失
        this.config = deepMerge(this.config, customConfig);
    }

    // 主要请求部分
    request(options = {}) {
        // 检查请求拦截
        if (this.interceptor.request && typeof this.interceptor.request === 'function') {
            let tmpConfig = {};
            let interceptorRequest = this.interceptor.request(options);
            if (interceptorRequest === false) {
                // 返回一个处于pending状态中的Promise，来取消原promise，避免进入then()回调
                return new Promise(()=>{});
            }
            this.options = interceptorRequest;
        }
        options.dataType = options.dataType || this.config.dataType;
        options.responseType = options.responseType || this.config.responseType;
        options.url = options.url || '';
        options.params = options.params || {};
        options.header = Object.assign({}, this.config.header, options.header);
        options.method = options.method || this.config.method;

        return new Promise((resolve, reject) => {
            options.complete = (response) => {
                // 请求返回后，隐藏loading(如果请求返回快的话，可能会没有loading)
                uni.hideLoading();
                // 清除定时器，如果请求回来了，就无需loading
                clearTimeout(this.config.timer);
                this.config.timer = null;
                // 判断用户对拦截返回数据的要求，如果originalData为true，返回所有的数据(response)到拦截器，否则只返回response.data
                if(this.config.originalData) {
                    // 判断是否存在拦截器
                    if (this.interceptor.response && typeof this.interceptor.response === 'function') {
                        let resInterceptors = this.interceptor.response(response);
                        // 如果拦截器不返回false，就将拦截器返回的内容给this.$u.post的then回调
                        if (resInterceptors !== false) {
                            resolve(resInterceptors);
                        } else {
                            // 如果拦截器返回false，意味着拦截器定义者认为返回有问题，直接接入catch回调
                            reject(response);
                        }
                    } else {
                        // 如果要求返回原始数据，就算没有拦截器，也返回最原始的数据
                        resolve(response);
                    }
                } else {
                    if (response.statusCode == 200) {
                        if (this.interceptor.response && typeof this.interceptor.response === 'function') {
                            let resInterceptors = this.interceptor.response(response.data);
                            if (resInterceptors !== false) {
                                resolve(resInterceptors);
                            } else {
                                reject(response.data);
                            }
                        } else {
                            // 如果不是返回原始数据(originalData=false)，且没有拦截器的情况下，返回纯数据给then回调
                            resolve(response.data);
                        }
                    } else {
                        // 不返回原始数据的情况下，服务器状态码不为200，modal弹框提示
                        // if(response.errMsg) {
                        //     uni.showModal({
                        //         title: response.errMsg
                        //     });
                        // }
                        reject(response)
                    }
                }
            }

            // 判断用户传递的URL是否/开头,如果不是,加上/，这里使用了uView的test.js验证库的url()方法
            options.url = validate.url(options.url) ? options.url : (this.config.baseUrl + (options.url.indexOf('/') == 0 ?
                options.url : '/' + options.url));
            
            // 是否显示loading
            // 加一个是否已有timer定时器的判断，否则有两个同时请求的时候，后者会清除前者的定时器id
            // 而没有清除前者的定时器，导致前者超时，一直显示loading
            if(this.config.showLoading && !this.config.timer) {
                this.config.timer = setTimeout(() => {
                    uni.showLoading({
                        title: this.config.loadingText,
                        mask: this.config.loadingMask
                    })
                    this.config.timer = null;
                }, this.config.loadingTime);
            }
            uni.request(options);
        })
        // .catch(res => {
        //     // 如果返回reject()，不让其进入this.$u.post().then().catch()后面的catct()
        //     // 因为很多人都会忘了写后面的catch()，导致报错捕获不到catch
        //     return new Promise(()=>{});
        // })
    }

    constructor() {
        this.config = {
            baseUrl: '', // 请求的根域名
            // 默认的请求头
            header: {},
            method: 'POST',
            // 设置为json，返回后uni.request会对数据进行一次JSON.parse
            dataType: 'json',
            // 此参数无需处理，因为5+和支付宝小程序不支持，默认为text即可
            responseType: 'text',
            showLoading: true, // 是否显示请求中的loading
            loadingText: '请求中...',
            loadingTime: 800, // 在此时间内，请求还没回来的话，就显示加载中动画，单位ms
            timer: null, // 定时器
            originalData: false, // 是否在拦截器中返回服务端的原始数据，见文档说明
            loadingMask: true, // 展示loading的时候，是否给一个透明的蒙层，防止触摸穿透
        }
    
        // 拦截器
        this.interceptor = {
            // 请求前的拦截
            request: null,
            // 请求后的拦截
            response: null
        }

        // get请求
        this.get = (url, data = {}, header = {}) => {
            return this.request({
                method: 'GET',
                url,
                header,
                data
            })
        }

        // post请求
        this.post = (url, data = {}, header = {}) => {
            return this.request({
                url,
                method: 'POST',
                header,
                data
            })
        }
        
        // put请求，不支持支付宝小程序(HX2.6.15)
        this.put = (url, data = {}, header = {}) => {
            return this.request({
                url,
                method: 'PUT',
                header,
                data
            })
        }
        
        // delete请求，不支持支付宝和头条小程序(HX2.6.15)
        this.delete = (url, data = {}, header = {}) => {
            return this.request({
                url,
                method: 'DELETE',
                header,
                data
            })
        }
    }
}
export default new Request
